;; The first four lines of this file were added by Dracula.
;; They tell DrScheme that this is a Dracula Modular ACL2 program.
;; Leave these lines unchanged so that DrScheme can properly load this file.
#reader(planet "reader.rkt" ("cce" "dracula.plt") "modular" "lang")
(require "ihipstafy.lisp")
(require "icommon.lisp")
(require "iimage.lisp")

; The Hipstafy module, responsible for creating Andy Warhol-esque
; reproductions of images. That is, it makes a new image, each of
; whose quadrants is the original image with a different hue.
(module MHipstafy
  (include-book "avl-rational-keys" :dir :teachpacks)
  (import ICommon)
  (import IImage)
  
  ; Turns a given pixel to a given h value.
  ;
  ; pre: r - the original pixel's r value
  ;      g - the original pixel's g value
  ;      b - the original pixel's b value
  ;      h - the hue value to change the pixel to
  ;
  ; post: a list of r, g, and b values that have been
  ; adjusted to the given hue
  (defun PixelToHue (r g b h)
    (if (and (<= r 255) (>= r 0)
             (<= g 255) (>= g 0)
             (<= b 255) (>= b 0)
             (<= h 360) (>= h 0))
        (let* ((hsv (RGB-to-HSV r g b))
               (s   (cadr hsv))
               (v   (caddr hsv)))
          (HSV-to-RGB h s v))
        "Invalid RGB value."))
  
  ; The helper function to Hipstafy, which actually processes each pixel
  ; and puts them into the new tree.
  ;
  ; pre: x - the current x coord being processed
  ;      y - the current y coord being processed
  ;      width - the width of the original image
  ;      height - the height of the original image
  ;      oldtree - the original tree's image
  ;      newtree - the new tree to put the hipstafy'd image in
  ;
  ; post: a new bitmap tree, hipstafy'd
  (defun HipstafyHelper (x y width height oldtree newtree)
    (let* ((nextX (getNextXCoordinate x width))
           (nextY (getNextYCoordinate x y width))
           (currpixel (getPixel oldtree x y))
           (r (car currpixel))
           (g (cadr currpixel))
           (b (caddr currpixel))
           ; make 4 copies of the original pixel, but alter the hue on each
           (newpixel1 (PixelToHue r g b 89))
           (newpixel2 (PixelToHue r g b 179))
           (newpixel3 (PixelToHue r g b 269))
           (newpixel4 (PixelToHue r g b 359))
           ; insert each one into the new tree, but change the quadrant
           (tr1 (insertPixelAsRGBList newtree x y newpixel1))
           (tr2 (insertPixelAsRGBList tr1 (+ x height) y newpixel2))
           (tr3 (insertPixelAsRGBList tr2 x (+ y width) newpixel3))
           (tr4 (insertPixelAsRGBList tr3 (+ x height) (+ y width) newpixel4)))
        (if (isValidPixel nextX nextY width height)
            (HipstafyHelper nextX nextY width height oldtree tr4)
            tr4)))
  
  ; The Hipstafy function, which takes a tree and calls its helper
  ; function to produce the new image.
  ;
  ; pre: tree - a bitmap tree
  ; post: a new bitmap tree with the processed image
  (defun MainHipstafy (tree)
    (let* ((oldheader (getHeader tree))
           (oldheight (getHeight tree))
           (oldwidth (getWidth tree))
           (newwidth (* 2 oldwidth))
           (newheight (* 2 oldheight))
           (tmptree (avl-insert (empty-tree) -1 oldheader))
           (newtree (setHeight (setWidth tmptree newwidth) newheight)))
      (mv (HipstafyHelper 1 oldheight oldwidth oldheight tree newtree) (list "Sucessfully hipstafied image."))))
  
  (export Ihipstafy))